#include "comm/my_queue.h"
#include "comm/my_log.h"

typedef struct {
    int a;
    my_queue_t queue;
} test_obj_t;

void test_queue() {
    test_obj_t a1 = {a:1};
    test_obj_t a2 = {a:2};
    test_obj_t a3 = {a:3};
    test_obj_t a4 = {a:4};
    test_obj_t a5 = {a:5};

    my_queue_t queue_a;
    my_queue_init(&queue_a);
    my_queue_insert_head(&queue_a, &a1.queue);
    my_queue_insert_head(&queue_a, &a2.queue);
    my_queue_insert_head(&queue_a, &a3.queue);
    my_queue_insert_head(&queue_a, &a4.queue);
    my_queue_insert_head(&queue_a, &a5.queue);

    my_queue_t *last;
    test_obj_t *data;
    int  i = 1;
    while(!my_queue_empty(&queue_a)) {
        last = my_queue_last(&queue_a);
        my_queue_remove(last);
        data = my_queue_data(last, test_obj_t, queue);
        if (data->a != i) {
            MY_LOG_FATAL("except %d, but got %d", i, data->a);
        }
        i++;
    }

    my_queue_insert_tail(&queue_a, &a1.queue);
    my_queue_insert_tail(&queue_a, &a2.queue);
    my_queue_insert_tail(&queue_a, &a3.queue);
    my_queue_insert_tail(&queue_a, &a4.queue);
    my_queue_insert_tail(&queue_a, &a5.queue);

    my_queue_t *head;
    i = 1;
    while(!my_queue_empty(&queue_a)) {
        head = my_queue_head(&queue_a);
        my_queue_remove(head);
        data = my_queue_data(head, test_obj_t, queue);
        if (data->a != i) {
            MY_LOG_FATAL("except %d, but got %d", i, data->a);
        }
        i++;
    }
}

void test_queue_move() {
    test_obj_t a1 = {a:1};
    test_obj_t a2 = {a:2};
    test_obj_t a3 = {a:3};
    test_obj_t a4 = {a:4};
    test_obj_t a5 = {a:5};

    my_queue_t queue_a;
    my_queue_init(&queue_a);
    my_queue_insert_head(&queue_a, &a1.queue);
    my_queue_insert_head(&queue_a, &a2.queue);
    my_queue_insert_head(&queue_a, &a3.queue);
    my_queue_insert_head(&queue_a, &a4.queue);
    my_queue_insert_head(&queue_a, &a5.queue);

    test_obj_t b1 = {a:11};
    test_obj_t b2 = {a:12};
    test_obj_t b3 = {a:13};
    test_obj_t b4 = {a:14};
    test_obj_t b5 = {a:15};

    my_queue_t queue_b;
    my_queue_init(&queue_b);
    my_queue_insert_head(&queue_b, &b1.queue);
    my_queue_insert_head(&queue_b, &b2.queue);
    my_queue_insert_head(&queue_b, &b3.queue);
    my_queue_insert_head(&queue_b, &b4.queue);
    my_queue_insert_head(&queue_b, &b5.queue);

    my_queue_move(&queue_a, &queue_b);

    if (!my_queue_empty(&queue_a)) {
        MY_LOG_FATAL("except true, but got false");
    }

    my_queue_t *last;
    test_obj_t *data;
    int i = 11;
    while(!my_queue_empty(&queue_b)) {
        last = my_queue_last(&queue_b);
        my_queue_remove(last);
        data = my_queue_data(last, test_obj_t, queue);
        if (data->a != i) {
            MY_LOG_FATAL("except %d, but got %d", i, data->a);
        }
        
        MY_LOG_DEBUG("%d", i);

        i++;
        if (i == 16) {
            i = 1;
        }
    }
}

void test_queue_move_to_empty_queue() {
    test_obj_t a1 = {a:1};
    test_obj_t a2 = {a:2};
    test_obj_t a3 = {a:3};
    test_obj_t a4 = {a:4};
    test_obj_t a5 = {a:5};

    my_queue_t queue_a;
    my_queue_init(&queue_a);
    my_queue_insert_head(&queue_a, &a1.queue);
    my_queue_insert_head(&queue_a, &a2.queue);
    my_queue_insert_head(&queue_a, &a3.queue);
    my_queue_insert_head(&queue_a, &a4.queue);
    my_queue_insert_head(&queue_a, &a5.queue);

    my_queue_t queue_b;
    my_queue_init(&queue_b);
    my_queue_move(&queue_a, &queue_b);

    my_queue_t *last;
    test_obj_t *data;
    int i = 1;
    while(!my_queue_empty(&queue_b)) {
        last = my_queue_last(&queue_b);
        my_queue_remove(last);
        data = my_queue_data(last, test_obj_t, queue);
        if (data->a != i) {
            MY_LOG_FATAL("except %d, but got %d", i, data->a);
        }

        MY_LOG_DEBUG("%d", i);

        i++;
    }

}

int main() {
    test_queue();
    test_queue_move();
    test_queue_move_to_empty_queue();

    MY_LOG_DEBUG("test pass");
    return 0;
}
